package com.compunit.composite.a;

import java.awt.IllegalComponentStateException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;

import org.compunit.Provide;
import org.compunit.Require;
import org.compunit.interfaces.IComponent;
import org.compunit.interfaces.IResourceRetriever;

import com.compunit.composite.a.interfaces.IDriver;
import com.compunit.composite.a.interfaces.IPrinter;

@Provide({IDriver.class})
@Require({IPrinter.class})
public class Driver implements IDriver {
	
	private final Thread thread;
	private final Random random;
	private volatile boolean finished;
	
	private final List<IPrinter> printers;
	
	public Driver() {
		this.thread = new Thread(this);
		this.random = new Random();
		this.finished = false;
		this.printers = new ArrayList<IPrinter>();
	}

	@Override
	public boolean activate(final IResourceRetriever handler) throws Exception {
		if(this.printers == null && this.printers.isEmpty()) {
			throw new IllegalComponentStateException("No available printer.");
		}
		this.thread.start();
		return true;
	}

	@Override
	public boolean connect(final IComponent unit, final String interfaceName) throws Exception {
		if(unit instanceof IPrinter) {
			this.printers.add((IPrinter)unit);
			return true;
		}
		return false;
	}

	@Override
	public void deactivate() throws Exception {
		this.finished = true;
		System.out.println("Driver shutting down.");
	}

	@Override
	public void run() {
		while(!this.finished) {
			// Generate a random word.
			final int length = (this.random.nextInt() & 10) + 10;
			final StringBuilder builder = new StringBuilder("Gibberish: ");
			for(int i = 0; i < length; i++) {
				final int offset = this.random.nextInt() & 25;
				final char c = (char)('a' + offset);
				builder.append(c);
			}
			// Print.
			for(final IPrinter printer : this.printers) {
				printer.print(builder.toString());
			}
			// Sleep.
			try {
				TimeUnit.MILLISECONDS.sleep(1500);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}
